package com.zhouhailin.reflection;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 通过反射调用方法
 *
 * @Author：zhouhailin
 * @Date： 2023/2/13
 */
public class ReflectionAccessMethod {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {

        // 1、得到 Boss 类对应的 Class 对象
        Class<?> bossClass = Class.forName("com.zhouhailin.reflection.Boss");
        // 2、创建对象
        Object o = bossClass.newInstance();
        // 3、调用 public 的 hi 方法
//        Method hi = bossClass.getMethod("hi", String.class);
        // 获取 hi 方法对象
        Method hi = bossClass.getDeclaredMethod("hi", String.class);
        // 调用了 hi 方法
        hi.invoke(o, "zhouhailin");


        // 4、调用 private static 方法
        // 4.1）获取 say 方法对象
        Method say = bossClass.getDeclaredMethod("say", int.class, String.class, char.class);
        // 4.2）因为 say 方法是 private, 所以需要暴破，原理和前面讲的构造器和属性一样
        say.setAccessible(true);
        System.out.println(say.invoke(o, 100, "张三丰", '男'));
        // 4.3）因为 say 方法是 static 的，还可以这样调用 ，可以传入 null
        System.out.println(say.invoke(null, 200, "张丰", '男'));


        // 5、在反射中，如果方法有返回值，统一返回 Object，但是他运行类型和方法定义的返回类型一致
        Object reValue = say.invoke(null, 300, "张一", '男');
        // 返回值：reValue 的运行类型 = class java.lang.String
        System.out.println("reValue 的运行类型 = " + reValue.getClass());


        Method m1 = bossClass.getDeclaredMethod("m1");
        Object reValue2 = m1.invoke(o);
        // 返回值：reValue2 的运行类型 = class com.zhouhailin.reflection.Monster
        System.out.println("reValue2 的运行类型 = " + reValue2.getClass());
    }
}

class Monster {
}

class Boss {
    public int age;
    private static String name;

    /**
     * 构造器
     */
    public Boss() {
    }

    public Monster m1() {
        return new Monster();
    }

    /**
     * 静态方法
     *
     * @param n
     * @param s
     * @param c
     * @return
     */
    private static String say(int n, String s, char c) {
        return n + " " + s + " " + c;
    }

    /**
     * 普通 public 方法
     *
     * @param s
     */
    public void hi(String s) {
        System.out.println("hi " + s);
    }
}